package com.xplay.xpocker.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xplay.xpocker.business.ResultFul;
import com.xplay.xpocker.config.security.VerificationUtil;
import com.xplay.xpocker.entity.system.SysUser;
import com.xplay.xpocker.entity.system.SysUserDTO;
import com.xplay.xpocker.service.system.ISysUserService;
import com.xplay.xpocker.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.security.interfaces.RSAPrivateKey;
import java.util.UUID;

/**
 * @author wanjie
 * @date 2021/4/22 10:19
 */
@RestController
@RequestMapping(value = DictionaryUrlConst.ControllerHeader.sys, produces = "application/json;charset=UTF-8")
@PropertySource(value = "classpath:filepath.properties")
public class SystemController {
    @Value(value = "${security.private-key}")
    private String privateKeyStr;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private VerificationUtil verificationUtil;

    @Value("${linux.download.file.path}")
    private String linuxFileRootPath;

    @Value("${windows.download.file.path}")
    private String windowsFileRootPath;


    @PostMapping(value = DictionaryUrlConst.UserController.login)
    public ResultFul<SysUserDTO> userLogin(@RequestBody SysUserDTO userDTO) {
        BusinessAssertion.isNull("请合法访问", userDTO, userDTO.getSysUser(), userDTO.getSysUser().getUsername(), userDTO.getSysUser().getPassword());
        BusinessAssertion.isNull("请输入验证码", userDTO.getVerificationMode(), userDTO.getVerificationMode().getX(), userDTO.getVerificationMode().getId(), userDTO.getVerificationMode().getY());
        verificationUtil.checkGenerateCode(userDTO.getVerificationMode(), true);
        RSAPrivateKey privateKey = RSAUtils.getPrivateKey(privateKeyStr);
        SysUserDTO userInfo = sysUserService.queryUserInfoByUserName(userDTO.getSysUser().getUsername());
        String decodePassword = RSAUtils.privateDecrypt(userDTO.getSysUser().getPassword(), privateKey);
        String privateDecrypt = RSAUtils.privateDecrypt(userInfo.getSysUser().getPassword(), privateKey);
        BusinessAssertion.isTrue("账号或者密码错误", !decodePassword.equals(privateDecrypt));
        String token = JwtUtils.doGenerateToken(userInfo.getSysUser().getUsername());
        userInfo.setTokenAuthority(token);
        return ResultFul.ok(userInfo);
    }

    @PostMapping(value = DictionaryUrlConst.UserController.create)
    public ResultFul<String> createUser(@RequestBody SysUserDTO userDTO) {
        BusinessAssertion.isNull("请输入用户信息", userDTO, userDTO.getSysUser(), userDTO.getSysUser().getUsername(), userDTO.getSysUser().getPassword());
        BusinessAssertion.isNull("请输入验证码", userDTO.getVerificationMode(), userDTO.getVerificationMode().getX(), userDTO.getVerificationMode().getId(), userDTO.getVerificationMode().getY());
        verificationUtil.checkGenerateCode(userDTO.getVerificationMode(), true);
        SysUser sysUser = userDTO.getSysUser();
        RSAPrivateKey privateKey = RSAUtils.getPrivateKey(privateKeyStr);
        String decodePassword = RSAUtils.privateDecrypt(userDTO.getSysUser().getPassword(), privateKey);
        Assertion.isTrue("用户名过于简陋", !sysUser.getUsername().matches(RegExpConstant.userName));
        Assertion.isTrue("密码过于简陋", !decodePassword.matches(RegExpConstant.password));
        sysUserService.addUser(sysUser);
        return ResultFul.ok("注册成功");
    }

    @PostMapping(value = DictionaryUrlConst.UserController.update)
    public ResultFul<String> updateUser(@RequestBody SysUser userInfo) {
        BusinessAssertion.isNull("请输入用户信息", userInfo);
        sysUserService.updateUser(userInfo);
        return ResultFul.ok("修改成功");
    }


    @PostMapping(value = "/upload/**")
    @ResponseBody
    public ResultFul<String> upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
        String suffixName = null;
        String filePath = linuxFileRootPath + extractPathFromPattern(request);
        String os = System.getProperty("os.name");
        if (os.toLowerCase().startsWith("win")) {
            filePath = windowsFileRootPath + extractPathFromPattern(request);
        }
        if (file.isEmpty()) {
            return ResultFul.fail("上传失败");
        }
        File rootPath = new File(filePath);
        if (!rootPath.exists()) {
            rootPath.mkdirs();
        }
        byte[] b = new byte[3];
        try {
            file.getInputStream().read(b, 0, b.length);
            String fileType = bytesToHexString(b);
            fileType = fileType.toUpperCase();
            suffixName = TypeDict.checkType(fileType);
            BusinessAssertion.isNull("无法认识的文件类型",suffixName);
        } catch (IOException e) {
            e.printStackTrace();
            return ResultFul.fail("上传失败");
        }
        String fileName = UUID.randomUUID().toString().replaceAll("-", "") + suffixName;
        File dest = new File(filePath + "/" + fileName);
        try {
            file.transferTo(dest);
        } catch (IOException e) {
        }
        return ResultFul.ok(fileName);
    }

    public static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder();
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }

    private String extractPathFromPattern(final HttpServletRequest request) {
        String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
        String bestMatchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
        return new AntPathMatcher().extractPathWithinPattern(bestMatchPattern, path);
    }
}
